package io.kiki.sba.registry.store.jdbc.repository.impl;

import io.kiki.sba.registry.common.model.metaserver.MultiClusterSyncInfo;
import io.kiki.sba.registry.store.api.config.DefaultCommonConfig;
import io.kiki.sba.registry.store.api.meta.MultiClusterSyncRepository;
import io.kiki.sba.registry.store.api.meta.RecoverConfig;
import io.kiki.sba.registry.store.jdbc.constant.TableEnum;
import io.kiki.sba.registry.store.jdbc.convertor.MultiClusterSyncConvertor;
import io.kiki.sba.registry.store.jdbc.domain.MultiClusterSyncDomain;
import io.kiki.sba.registry.store.jdbc.mapper.MultiClusterSyncMapper;
import io.kiki.sba.registry.store.jdbc.version.config.BaseConfigRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.Set;


public class MultiClusterSyncJdbcRepository implements MultiClusterSyncRepository, RecoverConfig {

    private static final Logger logger = LoggerFactory.getLogger(MultiClusterSyncJdbcRepository.class);
    @Autowired
    protected DefaultCommonConfig defaultCommonConfig;
    @Autowired
    private MultiClusterSyncMapper multiClusterSyncMapper;
    private Configer configer;

    public MultiClusterSyncJdbcRepository() {
        configer = new Configer();
    }

    @Override
    public boolean insert(MultiClusterSyncInfo multiClusterSyncInfo) {
        try {
            MultiClusterSyncDomain domain = MultiClusterSyncConvertor.convert2Domain(multiClusterSyncInfo, defaultCommonConfig.getClusterId(tableName()));
            MultiClusterSyncDomain exist = configer.queryExistVersion(domain);
            if (exist != null) {
                logger.error("multi cluster sync info: {} exist when insert.", multiClusterSyncInfo);
                return false;
            }
            // it will throw duplicate key exception when parallel invocation
            configer.insert(domain);
        } catch (Throwable t) {
            logger.error("multi cluster sync info: {} insert error", multiClusterSyncInfo, t);
            return false;
        }

        return true;
    }

    @Override
    public boolean update(MultiClusterSyncInfo multiClusterSyncInfo, long expectVersion) {
        return configer.put(MultiClusterSyncConvertor.convert2Domain(multiClusterSyncInfo, defaultCommonConfig.getClusterId(tableName())), expectVersion);
    }

    @Override
    public Set<MultiClusterSyncInfo> queryLocalMultiClusterSyncInfoSet() {
        List<MultiClusterSyncDomain> domains = multiClusterSyncMapper.queryByCluster(defaultCommonConfig.getClusterId(tableName()));
        return MultiClusterSyncConvertor.convert2Infos(domains);
    }

    @Override
    public int remove(String remoteDataCenter, long dataVersion) {
        return multiClusterSyncMapper.remove(defaultCommonConfig.getClusterId(tableName()), remoteDataCenter, dataVersion);
    }

    @Override
    public MultiClusterSyncInfo query(String remoteDataCenter) {
        MultiClusterSyncDomain multiClusterSyncDomain = multiClusterSyncMapper.query(defaultCommonConfig.getClusterId(tableName()), remoteDataCenter);
        return MultiClusterSyncConvertor.convert2Info(multiClusterSyncDomain);
    }

    @Override
    public String tableName() {
        return TableEnum.multi_cluster_sync_info.getTableName();
    }

    class Configer extends BaseConfigRepository<MultiClusterSyncDomain> {
        public Configer() {
            super("MultiClusterSyncInfo");
        }

        @Override
        protected MultiClusterSyncDomain queryExistVersion(MultiClusterSyncDomain multiClusterSyncDomain) {
            return multiClusterSyncMapper.query(multiClusterSyncDomain.getDataCenter(), multiClusterSyncDomain.getRemoteDataCenter());
        }

        @Override
        protected long insert(MultiClusterSyncDomain entry) {
            return multiClusterSyncMapper.save(entry);
        }

        @Override
        protected int updateWithExpectVersion(MultiClusterSyncDomain entry, long exist) {
            return multiClusterSyncMapper.update(entry, exist);
        }
    }
}
